#include "ModbusHandler.h"
#include <stdexcept>
#include <iostream>
#include <cstring>
#include <chrono>

// Modbus协议处理器构造函数
ModbusHandler::ModbusHandler(const ModbusConfig& cfg) : config(cfg), ctx(nullptr), isConnected(false) {
    initPoints();
}

// Modbus协议处理器析构函数
ModbusHandler::~ModbusHandler() {
    disconnect();
}

// 初始化测点信息
void ModbusHandler::initPoints() {
    points.clear();
    // 根据配置初始化测点信息
    for (int i = 0; i < config.register_count; ++i) {
        std::string pointId = "MODBUS_" + std::to_string(config.slave_id) + "_" + std::to_string(config.start_address + i);
        std::string pointName = "Register_" + std::to_string(config.start_address + i);
        // 默认单位为无量纲，上下限可根据实际情况调整
        points.emplace_back(pointId, pointName, "", 100.0f, 0.0f);
    }
}

// 连接到Modbus设备
bool ModbusHandler::connect(const std::string& configStr) {
    // 如果已有连接，先断开
    if (isConnected) {
        disconnect();
    }

    // 创建Modbus TCP上下文
    ctx = modbus_new_tcp(config.ip_address.c_str(), config.port);
    if (!ctx) {
        std::cerr << "Failed to create Modbus context: " << modbus_strerror(errno) << std::endl;
        return false;
    }

    // 设置超时
    modbus_set_response_timeout(ctx, 0, config.timeout_ms * 1000);

    // 设置从站地址
    modbus_set_slave(ctx, config.slave_id);

    // 建立连接
    int ret = modbus_connect(ctx);
    if (ret == -1) {
        std::cerr << "Modbus connection failed: " << modbus_strerror(errno) << std::endl;
        modbus_free(ctx);
        ctx = nullptr;
        return false;
    }

    isConnected = true;
    std::cout << "Modbus TCP connected to " << config.ip_address << ":" << config.port << std::endl;
    return true;
}

// 断开Modbus连接
void ModbusHandler::disconnect() {
    if (ctx) {
        modbus_close(ctx);
        modbus_free(ctx);
        ctx = nullptr;
    }
    isConnected = false;
    std::cout << "Modbus TCP disconnected" << std::endl;
}

// 读取Modbus数据
std::vector<PointData> ModbusHandler::readData() {
    if (!isConnected || !ctx) {
        throw std::runtime_error("Not connected to Modbus device");
    }

    std::vector<uint16_t> regs(config.register_count);
    int ret = modbus_read_registers(ctx, config.start_address, config.register_count, regs.data());

    if (ret == -1) {
        std::cerr << "Modbus read failed: " << modbus_strerror(errno) << std::endl;
        // 尝试重连
        disconnect();
        connect("");
        return {};
    }

    // 更新测点数据
    for (int i = 0; i < config.register_count && i < points.size(); ++i) {
        // 这里假设寄存器值为16位无符号整数，实际应用中可能需要根据设备手册进行转换
        points[i].value = static_cast<float>(regs[i]);
        points[i].timestamp = std::chrono::system_clock::now();
    }

    return points;
}